# -*- coding: utf-8 -*-
import json
import logging
from datetime import datetime

from common.account.model.account import Account
from common.game.model import *
from common.transaction.db import create_sharding_transaction
from common.transaction.model import TRANSACTION_TYPE, TRANSACTION_STATUS
from common.utils.db import list_object, get, parse_query_dct, generate_filter, get_count, get_orderby, paginate
from common.utils.decorator import sql_wrapper

from sqlalchemy import func

_LOGGER = logging.getLogger('bigbang')


@sql_wrapper
def list_bull(query_dct):
    return list_object(query_dct, BullTerm)


@sql_wrapper
def get_bull(id):
    return get(BullTerm, id)


@sql_wrapper
def list_bull_part(query_dct):
    return list_object(query_dct, BullPart)


@sql_wrapper
def game_table_list(query_dct, table):
    query_dct = parse_query_dct(query_dct, table)
    query = table.query.filter(generate_filter(query_dct, table))
    total_count = get_count(query)
    items = query.all()
    bet_total = 0.0
    award_total = 0.0
    for item in items:
        data = item.as_dict()
        bet_total = bet_total + float(data['bet_amount'])
        award_total = award_total + float(data['award_amount'])

    orderby = get_orderby(query_dct.get('$orderby'), table)
    if orderby is not None:
        query = query.order_by(orderby)
    query = paginate(query, query_dct)
    return query.all(), total_count, bet_total, award_total


@sql_wrapper
def list_lottery(query_dct):
    return list_object(query_dct, LotteryTerm)


@sql_wrapper
def list_lottery_part(query_dct):

    return list_object(query_dct, LotteryPart)


@sql_wrapper
def list_fruit(query_dct):
    return list_object(query_dct, GuessFruitTerm)


@sql_wrapper
def list_fruit_part(query_dct):
    return list_object(query_dct, GuessFruitParticipate)


@sql_wrapper
def list_kfc_part(query_dct):
    return list_object(query_dct, KfcRecord)


_ODDS_CONF = {
    0: 3,
    1: 4,
    2: 5,
    3: 6,
    4: 10,
    5: 100,
}


@sql_wrapper
def fresh_lottery_part(part_id):
    part = LotteryPart.query.filter(LotteryPart.id == part_id).one()
    term_number = part.term_number
    term = LotteryTerm.query.filter(LotteryTerm.term_number == term_number).one()
    user_id, bet_index, bet_amount, award_amount = part.user_id, part.bet_index, part.bet_amount, part.award_amount
    real_award = bet_amount * _ODDS_CONF[bet_index]
    if term.status >= 2 and term.win_index == bet_index:
        if award_amount and award_amount == real_award:
            _LOGGER.warn('lottery part has awarded, %s-%s', part_id, award_amount)
            return
        makeup_award = real_award - award_amount
        _LOGGER.info('lottery part ready to makeup %s awarded for %s, origin %s',
                     makeup_award, part_id, award_amount)
        res = LotteryPart.query.filter(LotteryPart.id == part_id).filter(
            LotteryPart.award_amount == award_amount).update({
            'award_amount': real_award,
            'updated_at': datetime.utcnow()
        })
        if not res:
            _LOGGER.warn('lottery part has awarded in transaction, %s-%s',
                         term_number, part_id)
            return None
        account = Account.query.filter(Account.id == user_id).with_lockmode('update').one()
        account.balance += makeup_award
        account.withdraw += makeup_award
        account.save(auto_commit=False)
        create_sharding_transaction(user_id, {'type': TRANSACTION_TYPE.AWARD,
                                              'title': u'大转盘补发',
                                              'price': makeup_award,
                                              'balance': account.balance,
                                              'extend ': json.dumps({'term_number': term_number}),
                                              'status': TRANSACTION_STATUS.DONE,
                                              })
        orm.session.commit()
        return makeup_award


@sql_wrapper
def game_table_list(query_dct, table):
    query_dct = parse_query_dct(query_dct, table)
    query = table.query.filter(generate_filter(query_dct, table))
    total_count = get_count(query)
    bet_total = query.with_entities(func.sum(table.bet_amount)).scalar() or 0
    award_total = query.with_entities(func.sum(table.award_amount)).scalar() or 0

    orderby = get_orderby(query_dct.get('$orderby'), table)
    if orderby is not None:
        query = query.order_by(orderby)
    query = paginate(query, query_dct)
    return query.all(), total_count, bet_total, award_total

